/*
 * ProtocolParser.cpp
 *
 *  Created on: Sep 7, 2017
 */
#include <vector>
#include <string.h>
#include <system/Mutex.h>
#include "CommDef.h"
#include "uart/ProtocolParser.h"
#include "utils/Log.h"
#include "ProtocolCustom.h"
#ifdef DEBUG_PRO_DATA
#include "logic/global_variables.h"
#endif
static Mutex sLock;
static std::vector<OnProtocolDataUpdateFun> sProtocolDataUpdateListenerList;

void registerProtocolDataUpdateListener(OnProtocolDataUpdateFun pListener) {
	Mutex::Autolock _l(sLock);
	LOGD("registerProtocolDataUpdateListener\n");
	if (pListener != NULL) {
		sProtocolDataUpdateListenerList.push_back(pListener);
	}
}

void unregisterProtocolDataUpdateListener(OnProtocolDataUpdateFun pListener) {
	Mutex::Autolock _l(sLock);
	LOGD("unregisterProtocolDataUpdateListener\n");
	if (pListener != NULL) {
		std::vector<OnProtocolDataUpdateFun>::iterator iter = sProtocolDataUpdateListenerList.begin();
		for (; iter != sProtocolDataUpdateListenerList.end(); iter++) {
			if ((*iter) == pListener) {
				sProtocolDataUpdateListenerList.erase(iter);
				return;
			}
		}
	}
}

static void notifyProtocolDataUpdate(const SProtocolData &data) {
	Mutex::Autolock _l(sLock);
	std::vector<OnProtocolDataUpdateFun>::const_iterator iter = sProtocolDataUpdateListenerList.begin();
	for (; iter != sProtocolDataUpdateListenerList.end(); iter++) {
		(*iter)(data);
	}
}

static SProtocolData sProtocolData;

SProtocolData& getProtocolData() {
	return sProtocolData;
}

/**
 * 获取校验码
 * Get checksum code
 */
UINT16 getCheckSum(const BYTE *pData, int len) {
	int sum = 0;
	for (int i = 0; i < len; ++i) {
		sum += pData[i];
	}

	return (UINT16)sum;
}

static void procParseProduct(const BYTE *pData){
		// 字节1
	    sProtocolData.inquiry_a2.RespSelfPrimingPump = GETBIT(pData[1], 7);
	    sProtocolData.inquiry_a2.RespHeatingFilm = GETBIT(pData[1], 6);
	    sProtocolData.inquiry_a2.RespPushRodMotorForward = GETBIT(pData[1], 5);
	    sProtocolData.inquiry_a2.RespDrainBoxPump = GETBIT(pData[1], 4);
	    sProtocolData.inquiry_a2.RespIceMakingPump = GETBIT(pData[1], 3);
	    sProtocolData.inquiry_a2.RespExhaustFan = GETBIT(pData[1], 2);
	    sProtocolData.inquiry_a2.RespReservedValve = GETBIT(pData[1], 1);
	    sProtocolData.inquiry_a2.RespFridgeUVLight = GETBIT(pData[1], 0);

	    // 字节2
	    sProtocolData.inquiry_a2.RespIceWaterInletValve = GETBIT(pData[2], 7);
	    sProtocolData.inquiry_a2.RespIntakeFan = GETBIT(pData[2], 6);
	    sProtocolData.inquiry_a2.RespColdWaterTankInletValve = GETBIT(pData[2], 5);
	    sProtocolData.inquiry_a2.RespColdWaterTankCirculationPump = GETBIT(pData[2], 4);
	    sProtocolData.inquiry_a2.RespColdWaterDiaphragmPump = GETBIT(pData[2], 3);
	    sProtocolData.inquiry_a2.RespSynchronousMotor = GETBIT(pData[2], 2);
	    sProtocolData.inquiry_a2.RespDeicingValve = GETBIT(pData[2], 1);
	    sProtocolData.inquiry_a2.RespColdWaterTankAntiFreeze = GETBIT(pData[2], 0);

	    // 字节3 (bit5-0)
	    sProtocolData.inquiry_a2.RespPushRodMotorReverse = GETBIT(pData[3], 5);
	    sProtocolData.inquiry_a2.RespIceFullIRTransmitter = GETBIT(pData[3], 4);
	    sProtocolData.inquiry_a2.RespOpenWaterLevelProbe = GETBIT(pData[3], 3);
	    sProtocolData.inquiry_a2.RespOpenDeicingSensor = GETBIT(pData[3], 2);
	    sProtocolData.inquiry_a2.RespIceDispenserMotorForward = GETBIT(pData[3], 1);
	    sProtocolData.inquiry_a2.RespIceDispenserMotorReverse = GETBIT(pData[3], 0);

	    // 字节4 (bit6-0)
	    //上一次出冰微动开关
	    sProtocolData.inquiry_a2.pre_IceMicroSwitch = sProtocolData.inquiry_a2.IceDispenserMicroSwitch;
	    sProtocolData.inquiry_a2.IceDispenserMicroSwitch = GETBIT(pData[4], 6);

	    sProtocolData.inquiry_a2.DrainBoxWaterLevel = GETBIT(pData[4], 5);
	    sProtocolData.inquiry_a2.DeicingMicroSwitch = GETBIT(pData[4], 4);
	    sProtocolData.inquiry_a2.DetectionMicroSwitch = GETBIT(pData[4], 3);
	    sProtocolData.inquiry_a2.IceMakingWaterLevel = GETBIT(pData[4], 2);
	    sProtocolData.inquiry_a2.ColdWaterTankLowLevel = GETBIT(pData[4], 1);
	    sProtocolData.inquiry_a2.ColdWaterTankHighLevel = GETBIT(pData[4], 0);

	    // 字节5
	    sProtocolData.inquiry_a2.WaveRightData = (pData[5] >> 4) & 0x0F;  // 高四位
	    sProtocolData.inquiry_a2.WaveLeftData = pData[5] & 0x0F;          // 低四位

	    // 将高位和低位合并为 16 位值
	    sProtocolData.inquiry_a2.DeicingSensorAD = MAKEWORD(pData[7], pData[6]);
	    sProtocolData.inquiry_a2.WaterLevelProbeAD = MAKEWORD(pData[9], pData[8]);
	    sProtocolData.inquiry_a2.IceFullAD = MAKEWORD(pData[11], pData[10]);
	    sProtocolData.inquiry_a2.IceMakingPumpAD = MAKEWORD(pData[13], pData[12]);
	    sProtocolData.inquiry_a2.DrainBoxPumpAD = MAKEWORD(pData[15], pData[14]);
	    sProtocolData.inquiry_a2.ColdWaterTankNTCTemp = ( (MAKEWORD(pData[17], pData[16])) / 10);
	    sProtocolData.inquiry_a2.IceMakingWaterNTCTemp = ( (MAKEWORD(pData[19], pData[18])) / 10);

#ifdef DEBUG_PRO_DATA
		std::string str;
		char tmp[4] = {4};
		for(uint32_t level1 = 0; level1 < 20; ++level1)
		{
			snprintf(tmp, sizeof(tmp), "%.2X ", pData[level1]);
			str.append(tmp);
		}
		if(pData[20] == INQUIRY_CMD_A2){
			Global::Log::inquiry_a2_log = str.c_str();
		}
		LOGD("--%d-- --%s-- 接收数据：%s\n", __LINE__, __FILE__, str.c_str());
#endif

	    notifyProtocolDataUpdate(sProtocolData);
}

/**
 * 功能：制冰解析协议
 * Function: Parse protocol
 * 参数：pData 协议数据，len 数据长度
 * Parameters: pData - protocol data, len - data length
 * 返回值：剩下未解析协议的长度
 */
int parseProtocolProduct(const BYTE *pData, UINT len) {
	UINT remainLen = len;	// 剩余数据长度 Remaining data length
	// 数据包长度 Packet length 固定为 23
 	UINT frameLen;	// 帧长度 Frame length

	while (remainLen >= DATA_PACKAGE_MIN_LEN) {
		// 找到一帧数据的数据头
    // Find the data header of a frame of data
		while ( (pData[0] != 0xAA) && (pData[20] != INQUIRY_CMD_A2) ) {
			pData++;
			remainLen--;
			continue;
		}

		if (remainLen < DATA_PACKAGE_MIN_LEN) {
			break;
		}

		frameLen = DATA_PACKAGE_MIN_LEN;

		// 打印一帧数据，需要时在CommDef.h文件中打开DEBUG_PRO_DATA宏
#ifdef DEBUG_PRO_DATA
		LOGD("frameLen=%d\n",frameLen);
		for (UINT i = 0; i < frameLen; ++i) {
			LOGD("%x ", pData[i]);
		}
		LOGD("pData[20]:%x ", pData[20]);
		LOGD("pData[22]:%x ", pData[22]);
		LOGD("\n");
#endif

		// 支持checksum校验，需要时在CommDef.h文件中打开PRO_SUPPORT_CHECK_SUM宏
//#ifdef PRO_SUPPORT_CHECK_SUM
		// 检测校验码 Checksum
		uint16_t crc = getCheckSum(&pData[1],DATA_PACKAGE_MIN_LEN - 3);
		uint16_t getcrc = MAKEWORD(pData[DATA_PACKAGE_MIN_LEN - 1], pData[DATA_PACKAGE_MIN_LEN - 2]);
		if (crc == getcrc) {
			// 解析一帧数据
//			LOGD("CheckSum success %x== %x!!!!!\n",crc,getcrc);
			procParseProduct(pData);
		} else {
			LOGE("CheckSum error %x!= %x!!!!!\n",crc,getcrc);
			for (UINT i = 0; i < frameLen; ++i) {
				LOGD("%x ", pData[i]);
			}
			LOGD("\n");
		}
		pData += frameLen;
		remainLen -= frameLen;
	}

	return len - remainLen;
}

/**
 * 功能：解析协议
 * 参数：pData 协议数据，len 数据长度
 * 返回值：实际解析协议的长度
 */
int parseProtocolCustom(const uint8_t *pData, uint32_t len) {
	uint32_t remain_len = len;
 	while (remain_len > 0) {
 		const uint8_t *pNext = NULL;
// 		uint8_t test_data[256]= {0x7E, 0x30, 0xC0, 0x02, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x19, 0x19, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x19, 0x7A, 0x7E};
 		bool ret = protocol::parse(pData, remain_len, pNext, sProtocolData);
 		if (pNext) {
 			remain_len -= pNext - pData;
 			pData = pNext;
 		} else {
 			remain_len = 0;
 		}

 		if (!ret) {
 			break;
		}

//		notifyProtocolDataUpdate(sProtocolData);
 	}

 	return len - remain_len;
}
